<!doctype html>
<title>Railroad Diagram Generator</title>
<link href="railroad.css" rel=stylesheet>

<textarea class='input'>Diagram(
  Optional('+', 'skip'),
  Choice(0,
    NonTerminal('name-start char'),
    NonTerminal('escape')),
  ZeroOrMore(
    Choice(0,
      NonTerminal('name char'),
      NonTerminal('escape'))))</textarea>
<div class='output-image'></div>
<textarea class='output-text' readonly></textarea>
<ul class=info>
	<li><label><input type=number min=1 value=8 width=3 id=option-vs> Minimum vertical separation between lines (in px)?</label>
	<li><label><input type=number min=2 value=10 id=option-ar> Arc radius for corners (in px)?</label>
	<li><label><input type=number min=1 value=8.5 step=.5 id=option-char-width> Average width of characters in "normal" (Terminal/NonTerminal) text (in px)?</label>
	<li><label><input type=number min=1 value=7 step=.5 id=option-comment-width> Average width of characters in Comment text (in px)?</label>
	<li><label>
		<select id=option-alignment>
			<option>center</option>
			<option>left</option>
			<option>right</option>
		</select>
		How should items be aligned when there's more space than they need?</label>
	<li><label><input type=checkbox id=option-odd-stroke checked> Is the stroke width an odd number of px? (Yes, in the default styles.)
	<li><label><input type=checkbox name=standalone id=option-standalone> Generate code for standalone SVG document?</label>
</ul>

<script type=module>
import rr, * as rrClass from "./railroad.js";
Object.assign(window, rr);
window.rrOptions = rrClass.Options;
console.log(rr);

const find = document.querySelector.bind(document);

find('.input').addEventListener('input', e=>process(e.target.value), false);
document.addEventListener('DOMContentLoaded', initialProcess, false);
window.addEventListener('hashchange', hashProcess, false);
find('.info').addEventListener('input', _=>process(), false);

function initialProcess() {
	if(location.hash && location.hash.length > 1) {
		const code = decodeURIComponent(location.hash.substr(1));
		const input = find('.input');
		input.textContent = code;
	}
	process();
}

function hashProcess() {
	if(location.hash && location.hash.length > 1) {
		const code = decodeURIComponent(location.hash.substr(1));
		const input = find('.input');
		if(input.value != code) {
			input.textContent = code;
			process(code);
		}
	}
}

function process(input) {
	if(!input) input = find('.input').value;
	const standalone = find('#option-standalone').checked;
	rrOptions.VS = parseInt(find("#option-vs").value, 10);
	rrOptions.AR = parseInt(find("#option-ar").value, 10);
	rrOptions.STROKE_ODD_PIXEL_LENGTH = find("#option-odd-stroke").checked;
	rrOptions.CHAR_WIDTH = parseInt(find("#option-char-width").value, 10);
	rrOptions.COMMENT_CHAR_WIDTH = parseInt(find("#option-comment-width").value, 10);
	rrOptions.INTERNAL_ALIGNMENT = find("#option-alignment").value;
	try {
		var result = eval(input).format();
		location.hash = "#" + encodeURIComponent(input);
	} catch (e) {
		find('.output-text').textContent = "Invalid input.\n" + e
		throw e;
	}
	find('.output-image').innerHTML = '';
	result.addTo(find('.output-image'));
	find('.output-text').textContent = standalone ? result.toStandalone() : result.toString();
	console.log(result);
}
</script>

<style>
@media all and (min-width: 400px) {
	html, body { margin: 0; padding: 0; height: 100%; }
	body {
		display: grid;
		grid-template:
			"input  code" 1fr
			"output info" 1fr
			/ auto   minmax(15em, auto);
		max-width: 100%;
	}
}
.input {
	grid-area: input;
}
.output-text {
	grid-area: code;
}
.output-image {
	grid-area: output;
	overflow:  auto;
}
.info {
	grid-area: info;
}
.info input[type=number], .info select {
	width:  60px;
	box-sizing:  border-box;
}
</style>
